<?php
/**
 * Created by PhpStorm.
 * User: pc
 * Date: 2025/1/15
 * Time: 12:54
 */

namespace app\common\service;


use app\common\helper\CommonHelper;
use app\models\EtcProductBan;
use app\models\EtcSendCreatorDayLog;
use app\models\EtcSendCreatorDetail;
use app\models\EtcTitles;
use app\models\QlUserTiktokProductGoods;
use app\models\TiktokUsers;
use app\modules\setting\models\yjrwsz\EtcRules;
use app\modules\setting\models\yjrwsz\SetYjrwszRwsz;
use yii\base\Exception;
use yii\db\Expression;
use yii\helpers\ArrayHelper;

class AutoSendMail
{
    public $day_times;
    public $job_num;
    public $creators_per_job;
    public $last_creator_send_id;
    public $product_num;
    /**
     * @var $setting SetYjrwszRwsz
     */
    public $setting;
    /**
     * @var Tpl
     */
    public $view;

    //发送邮件且创作者回复的邮箱
    const EMAIL = "tap@vikkc.com";
    /**
     * @var $service EdmService
     */
    public $service;
    /**
     * @var $kg KaiGuan
     */
    public $kg;
    public $rule_name = '';
    public function __construct()
    {
        $this->setting();
    }

    public function setting(){
        $setting = SetYjrwszRwsz::findOne();
        $setting_data = $setting->toArray();
        $this->day_times = intval(ArrayHelper::getValue($setting_data,'day_times'));
        $this->job_num = intval(ArrayHelper::getValue($setting_data,'job_num'));
        $this->creators_per_job = intval(ArrayHelper::getValue($setting_data,'creators_per_job'));
        $this->last_creator_send_id = intval(ArrayHelper::getValue($setting_data,'last_creator_send_id'));
        $this->product_num = intval(ArrayHelper::getValue($setting_data,'product_num'));
        $this->setting = $setting;
        $this->service = new EdmService();
        $this->view = new Tpl(Tpl::PRODUCT);
        $this->kg = new KaiGuan();
    }

    static function float($num){
        return CommonHelper::float($num);
    }

    /**
     * @return bool
     * @throws Exception
     */
    public function run(){
        if($this->day_times <= 0){
            //不执行批次的话，直接返回
            return false;
        }
        $setting = $this->setting;
        $day = date("Y-m-d");


        //执行某个批次，查询数据库，当前最大批次是否执行完毕。
        $day_row = EtcSendCreatorDayLog::find()
            ->andWhere(['day'=>$day])
            ->andWhere([
                'and',
                ['job_id'=>EtcSendCreatorDayLog::find()->andWhere(['day'=>$day])->max("job_id")],
                ['group_id'=>EtcSendCreatorDayLog::find()->andWhere(['day'=>$day])->max("group_id")],
            ])
            ->one();
        if($setting->zq_days > 1){
            if(!$day_row instanceof EtcSendCreatorDayLog){
                //今天没有执行的任务，则判断和最近一次任务相隔多少天
                $max_day = EtcSendCreatorDayLog::find()->max("day");
                if(!empty($max_day)){
                    $int_day_num = CommonHelper::getIntByDay($day,$max_day);
                    if($int_day_num < $setting->zq_days){
                        //相隔的天数没达到就终止执行。
                        return false;
                    }
                }
            }
        }
        if(!$day_row instanceof EtcSendCreatorDayLog){
            $group_id = 1;
            $job_id = 1;
            $day_row = $this->createDayRow($day,$group_id,$job_id);
        }else{
            $group_id = $day_row->group_id;
            $job_id =  $day_row->job_id;
        }

        $is_done = $this->isDone($day_row);
        if($is_done){
            $job_id++;
            if($job_id > $this->job_num){
                //重新计数
                $job_id = 1;
                $group_id++;
                if($group_id > $this->day_times){
                    echo "今日任务已执行完毕";
                    return true;
                }
            }
            //创建新的任务
            $day_row = $this->createDayRow($day,$group_id,$job_id);
        }

    }

    public function createDayRow($day,$group_id,$job_id){
        $day_row = EtcSendCreatorDayLog::find()->andWhere([
            'day' => $day,
            'group_id' => $group_id,
            'job_id' => $job_id,
        ])->one();
        if($day_row instanceof EtcSendCreatorDayLog){
            return $day_row;
        }
        $day_row = new EtcSendCreatorDayLog();
        $day_row->day = $day;
        $day_row->group_id = $group_id;
        $day_row->job_id = $job_id;
        $offset = rand(0,EtcTitles::find()->count()-1);
        $title_row = EtcTitles::find()->offset($offset)->one();
        $day_row->title = $title_row ? $title_row['title'] : 'NONE';
        $day_row->content = $this->getProductContent();
        $day_row->list_uid = $this->getApiListUid();
        $day_row->rule_name = $this->rule_name;
//        var_dump($this->rule_name,'11');
        if(!$day_row->save()){
            throw new Exception("生成记录失败，".print_r($day_row->errors,true));
        }
        return $day_row;
    }

    public function getFiles($alias){
        $dir = \Yii::getAlias($alias);
        $files = glob($dir . '/*.php'); // 获取所有.php文件

        return $files;
    }

    public function randTplFile($array){
        // 获取一个随机键
        $randomKey = array_rand($array);

        // 获取一个随机值
        $randomValue = $array[$randomKey];

        if(preg_match('/([^\/]+)\.php/',$randomValue,$out)){
            return $out[1];
        }
        return "there";
    }

    public function getProductContent(){
        $arr = range(0,3);
        $files = $this->getFiles(Tpl::PRODUCT);
        $tpl = $this->randTplFile($files);


        //三个类型产品
        $arr_products = [];
        foreach ($arr as $type){
            $list = $this->getProductByType($type);
//            var_dump($type,$list);

            if($list){
                foreach ($list as $v){
                    $arr_products[] = $v;
                }
            }
        }

//        throw new Exception("test");

        $html = $this->view->render($tpl,[
            'arr_products'=> $arr_products
        ]);

        return $html;
    }

    public function getBanIds(){
        return EtcProductBan::find()->select(['id'])->column();
    }

    public function getProductByType($type,$is_retry = false){
        if(!$is_retry && $this->kg->isRunningKg(KaiGuan::MULTI_RULES)){
            return $this->getProductByTypeMulti($type,$is_retry = false);
        }

        $query = QlUserTiktokProductGoods::find()->alias("t")->andWhere(['type'=>$type]);

        //过滤下架产品
        $query->andWhere(['not in','id',$this->getBanIds()]);

        if(!$is_retry){
            //过滤条件添加
            if(($value = $this->float($this->setting->goods_per_store) )> 0){
                //mysql 根据店铺分组，查出每个店铺前{n}个商品的id
                $sql = "SELECT id
FROM ( 
    SELECT 
        shop_code, 
        id, 
        @rn := IF(@prev_shop_code = shop_code, @rn + 1, 1) AS rn, 
        @prev_shop_code := shop_code 
    FROM 
        ql_user_tiktok_product_goods, (SELECT @rn := 0, @prev_shop_code := NULL) AS vars 
    ORDER BY shop_code, RAND()
) ranked_products 
WHERE rn <= {$value}";
                $query->andWhere(new Expression("id in ({$sql})"));
            }
            if(($value = $this->float($this->setting->min_sale) )> 0){
                $query->andWhere(['>=','product_sales',$value]);
            }

            if(($value = $this->float($this->setting->min_price) )> 0){
                $query->andWhere(['>=','price',$value]);
            }

            if(($value = $this->float($this->setting->min_pf) )> 0){
                $query->andWhere(['>=','product_rating',$value]);
            }

            if(($value = $this->float($this->setting->min_yj) )> 0){
                $query->andWhere(['>=','creator_commission_percent',$value]);
            }

            if(($value = $this->float($this->setting->is_bp) ) != 0){
                $type = QlUserTiktokProductGoods::EXCLUSIVE;
                if($value == -1){
                    $query->andWhere(['<>','type',$type]);
                }

                if($value == 1){
                    $query->andWhere(['type'=> $type]);
                }

            }

            if(($value = $this->float($this->setting->is_new) ) != 0){
                $type = QlUserTiktokProductGoods::GOODS;
                if($value == -1){
                    $query->andWhere(['<>','type',$type]);
                }

                if($value == 1){
                    $query->andWhere(['type'=> $type]);
                }

            }

            if(($value = $this->float($this->setting->is_brand) ) != 0){
                $type = QlUserTiktokProductGoods::SELLER;
                if($value == -1){
                    $query->andWhere(['<>','type',$type]);
                }

                if($value == 1){
                    $query->andWhere(['type'=> $type]);
                }

            }
            if(($value = $this->float($this->setting->drsj) ) != 0){
                if($value > 0){
                    $query->andWhere(new Expression("DATEDIFF(NOW(), created_at) <= {$value}"));
                }
            }
        }


        $query->select([
            'img',
            'name',
            'price',
            'creator_commission_percent',
            'product_sales',
            'product_rating',
            'link',
            'id',
            'type',
        ]);

        $limit = $this->product_num;
        $total = (clone $query)->count();
        if($total < $limit){
            $offset = 0;
        }else{
            $last = $total - $limit - 1;
            $offset = rand(0,$last);
        }

        $query->offset($offset)->limit($limit);
        $query->orderBy("RAND()");

        $list = $query->asArray()->all();
//        echo $query->createCommand()->rawSql;
        if(!$is_retry && empty($list)){
            $list = $this->getProductByType($type,true);
        }
        if(empty($this->rule_name)){
            $this->rule_name = "单任务设置";
        }
//        var_dump($this->rule_name,'33');
        return $list;
    }

    public function getProductByTypeMulti($type,$is_retry = false){
        $query = QlUserTiktokProductGoods::find()->alias("t")->andWhere(['type'=>$type]);

        //过滤下架产品
        $query->andWhere(['not in','id',$this->getBanIds()]);

        /**
         * @var $setting EtcRules
         */
        $setting = EtcRules::find()->orderBy("RAND()")->one();

        if(!$is_retry){
            //过滤条件添加
            if(($value = $this->float($setting->goods_per_store) )> 0){
                //mysql 根据店铺分组，查出每个店铺前{n}个商品的id
                $sql = "SELECT id
FROM ( 
    SELECT 
        shop_code, 
        id, 
        @rn := IF(@prev_shop_code = shop_code, @rn + 1, 1) AS rn, 
        @prev_shop_code := shop_code 
    FROM 
        ql_user_tiktok_product_goods, (SELECT @rn := 0, @prev_shop_code := NULL) AS vars 
    ORDER BY shop_code, RAND()
) ranked_products 
WHERE rn <= {$value}";
                $query->andWhere(new Expression("id in ({$sql})"));
            }
            if(($value = $this->float($setting->min_sale) )> 0){
                $query->andWhere(['>=','product_sales',$value]);
            }

            if(($value = $this->float($setting->min_price) )> 0){
                $query->andWhere(['>=','price',$value]);
            }

            if(($value = $this->float($setting->min_pf) )> 0){
                $query->andWhere(['>=','product_rating',$value]);
            }

            if(($value = $this->float($setting->min_yj) )> 0){
                $query->andWhere(['>=','creator_commission_percent',$value]);
            }

            if(($value = $this->float($setting->is_bp) ) != 0){
                $type = QlUserTiktokProductGoods::EXCLUSIVE;
                if($value == -1){
                    $query->andWhere(['<>','type',$type]);
                }

                if($value == 1){
                    $query->andWhere(['type'=> $type]);
                }

            }

            if(($value = $this->float($setting->is_new) ) != 0){
                $type = QlUserTiktokProductGoods::GOODS;
                if($value == -1){
                    $query->andWhere(['<>','type',$type]);
                }

                if($value == 1){
                    $query->andWhere(['type'=> $type]);
                }

            }

            if(($value = $this->float($setting->is_brand) ) != 0){
                $type = QlUserTiktokProductGoods::SELLER;
                if($value == -1){
                    $query->andWhere(['<>','type',$type]);
                }

                if($value == 1){
                    $query->andWhere(['type'=> $type]);
                }

            }
            if(($value = $this->float($setting->drsj) ) != 0){
                if($value > 0){
                    $query->andWhere(new Expression("DATEDIFF(NOW(), created_at) <= {$value}"));
                }
            }
        }


        $query->select([
            'img',
            'name',
            'price',
            'creator_commission_percent',
            'product_sales',
            'product_rating',
            'link',
            'id',
            'type',
        ]);

        $limit = $this->product_num;
        $total = (clone $query)->count();
        if($total < $limit){
            $offset = 0;
        }else{
            $last = $total - $limit - 1;
            $offset = rand(0,$last);
        }

        $query->offset($offset)->limit($limit);
        $query->orderBy("RAND()");

        $list = $query->asArray()->all();
//        echo $query->createCommand()->rawSql;
        if(!$is_retry && empty($list)){
            $list = $this->getProductByType($type,true);
        }
        if(empty($this->rule_name)){
            $this->rule_name = $setting->name;
        }

//        var_dump($this->rule_name,'00');
        return $list;
    }

    public static function getMarketPlacePic($url){
        $encode = base64_encode($url);
        return "http://test.vikoc.com/tiktokimg/{$encode}";
    }

    public static function toK($num){
        if($num > 1000){
            return intval($num/1000)."k";
        }
        if($num > 1000000){
            return intval($num/1000)."m";
        }
        return $num;
    }

    public function getApiListUid(){
        $arr_respone = $this->service->createList(self::EMAIL);
        $list_uid = ArrayHelper::getValue($arr_respone,'list_uid');
        if($list_uid){
            return $list_uid;
        }
        throw new Exception("通过接口创建list_uid失败");
    }

    /**
     * @param $day_row EtcSendCreatorDayLog
     * @return bool
     */
    public function isDone($day_row){
        //创建的记录数量是否等于创作者数量
        $detail_count = EtcSendCreatorDetail::find()->andWhere(['log_id'=>$day_row->id])->count();
        if($detail_count < $this->creators_per_job){
            //创作者数量不足，则增加200条创作者绑定
            $id = intval($this->last_creator_send_id);
            $dif = intval($this->creators_per_job) - intval($detail_count);
            $limit = 200;
            if($dif > 0 && $dif < 200){
                $limit = $dif;
            }
            $query = TiktokUsers::find()->andWhere(new Expression("email <> '' and email is not null"))->andWhere(['>','id',$id])->limit($limit);
            $list = $query->select(['email','id'])->asArray()->all();
            if(empty($list)){
                //查不出数据了，把id重置为0
                $this->settingReset();
            }else{
                $max_id = max(ArrayHelper::getColumn($list,'id'));
                $this->setLast($max_id);
                $arr_insert_data = array_map(function($row) use ($day_row){
                    return [
                        'email' => $row['email'],
                        'username' => $row['username'],
                        'list_uid' => $day_row->list_uid,
                        'log_id' => $day_row->id,
                        'status' => 0,
                    ];
                },$list);
                $fields = array_keys(ArrayHelper::getValue($arr_insert_data,"0"));
                \Yii::$app->db->createCommand()->batchInsert("etc_send_creator_detail",$fields,$arr_insert_data)->execute();
            }
            return false;
        }
        //未处理的记录，edm绑定邮箱
        $detail_count = EtcSendCreatorDetail::find()->andWhere(['log_id'=>$day_row->id,'status'=>0])->count();
        if($detail_count > 0){
            $query = EtcSendCreatorDetail::find()->andWhere(['log_id'=>$day_row->id,'status'=>0])->limit(200);
            foreach ($query->batch(10) as $batch){
                foreach ($batch as $row){
                    /**
                     * @var $row EtcSendCreatorDetail
                     */

                    $api_sub = $this->service->createSubscribers($day_row->list_uid,$row->email);
                    if(ArrayHelper::getValue($api_sub,'subscriber_uid')){
                        $row->status = 1;
                    }else{
                        $row->status = -1;
                    }
                    $row->save();
                }
            }
            return false;
        }
        //创建发送任务
        if($day_row->status === 0){
            $now = date("Ymd");
            $name = "【{$now}】{$day_row->title}";
            $run_at = date("Y-m-d H:i",strtotime("-12 hour"));

            $api_json = $this->service->createCampaigns($name,$day_row->list_uid,self::EMAIL,$run_at,$day_row->title,$day_row->content);
            if(ArrayHelper::getValue($api_json,'data.id')){
                $day_row->status = 1;
            }else{
                $day_row->status = -1;
            }
            $day_row->end_time = date("Y-m-d H:i:s");
            $day_row->save();
        }

        return true;
    }


    public function settingReset(){
        $this->setLast(0);
    }

    public function setLast($num){
        $num = intval($num);
        $setting = SetYjrwszRwsz::findOne();
        if($setting instanceof SetYjrwszRwsz){
            $setting->last_creator_send_id = $num;
            $setting->save();
        }
    }
}